package com.kcs.fxmargin.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import org.apache.log4j.Logger;

import com.kcs.common.utils.ConnectionUtils;
import com.kcs.common.utils.Constant;
import com.kcs.common.utils.OIDGenerator;
import com.kcs.common.utils.PropsUtils;
import com.kcs.common.utils.commonUtils;
import com.kcs.fxmargin.dao.MessageDao;
import com.kcs.fxmargin.model.CMessage;
import com.kcs.fxmargin.model.TRateDetail;
import com.kcs.fxmargin.model.TRateHeader;

public class ImportRateService {
	private static Logger log = Logger.getLogger(Constant.LOG_FX);
	private Logger logImport = Logger.getLogger(Constant.LOG_IMPORT_RATE);
	
	public static Map<String, String> message = new HashMap<String, String>();
	
	private Map generatePeriod(){
	    Map map = new HashMap();
	    String[] period = Constant.ALL_RATE_PERIOD;
	    if(commonUtils.isNotEmpty(period)){
	    	int indStartRate   = Constant.IND_RATE_VALUE_START_AT;    	int indStartPeriod = Constant.IND_PERIOD_VALUE_START_AT;
		    for(int i=0;i<period.length;i++){
		    	map.put(period[i], indStartRate+Constant.CSV_SPLIT+indStartPeriod);
		    	indStartRate++;
		    	indStartPeriod++;
		    }
	    }
	    return map;
	}

	
	private void mappingRateDetails(Map map, TRateHeader header,List tRateList,String[] datas,String userId) {
		
		Iterator it = map.entrySet().iterator(); 
		while (it.hasNext()) { 
			Map.Entry entry = (Map.Entry) it.next(); 
			String key = (String)entry.getKey(); 
			String val  = (String)entry.getValue(); 
			String[] valInd = val.split(Constant.CSV_SPLIT);
			int indRate   = Integer.parseInt(valInd[0]);
			int indDayCnt = Integer.parseInt(valInd[1]);

			TRateDetail m = new TRateDetail();
			m.setId(OIDGenerator.create());
			m.setRateHeaderId(header.getId());

			m.setCurr1(commonUtils.isNotEmpty(datas[0])?datas[0]:null);
			m.setCurr2(commonUtils.isNotEmpty(datas[1])?datas[1]:null);
			m.setRate(new BigDecimal(datas[indRate]));
			m.setDayCount(Integer.parseInt(datas[indDayCnt]));
			m.setPeriod(key);
			m.setRowVersion(1);
			m.setCreateBy(userId);
			m.setActiveStatus(Constant.ACTIVE_STATUS);							
			
			tRateList.add(m);
		}

	}

	private TRateHeader mappingRateHeader(File file,
			String[] datas,String userId) throws ParseException, Exception {
		 Time time;
		 TRateHeader header;
		 DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
		 Date date = (Date)formatter.parse(datas[2]);
		 time = new Time(date.getTime());
		 String asOfDate = datas[0];
		 header = new TRateHeader();
		 header.setId(OIDGenerator.create());
	     header.setAsOfDate(commonUtils.convertStringtoSQLDate(asOfDate,"dd/MM/yyyy"));
		 header.setTime(time);
		 String newPath = file.getAbsolutePath();
		 if(file.getAbsolutePath().length()>Constant.FILE_PATH_UNIX.length()){
			 int subLenght  = file.getAbsolutePath().lastIndexOf(File.separator)-Constant.FILE_PATH_UNIX.length();			
		     newPath = file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf(File.separator)-subLenght,file.getAbsolutePath().length());		  
		     newPath = newPath.substring(newPath.indexOf(File.separator),newPath.length());
		 }
		 //System.out.println("new file ->"+newPath);
		 header.setFilePath(newPath);
		 header.setRowVersion(1);
		 header.setCreateBy(userId);
		 header.setUpdateBy(userId);
		 header.setActiveStatus(Constant.ACTIVE_STATUS);
		return header;
	}
		
	public File	getFile(String filePath){
		File file = null;
		try{
			if(commonUtils.isNotEmpty(filePath)){
				file = new File(filePath);
				if(file.exists()){
					return file;
				}
			}
		}
		catch(Exception e){
			log.error("getFile:"+e);
		}
		return file;
	}
		
		
	public  List<String[]> readFile(File file) throws Exception{
		BufferedReader br  = null;
		List<String[]> tmp = null;
		try{
			tmp = new ArrayList();		
			FileInputStream inputStream = new FileInputStream(file);		
			br = new BufferedReader(new InputStreamReader(inputStream));	 
			String line = "";
			int l = 1;		
			while ((line = br.readLine()) != null) {				
				String[] datas = line.split(Constant.CSV_SPLIT,-1);
				tmp.add(datas);
				l++;
			}
		}
		catch(Exception e){
			log.error("readFile:"+e);
			throw e;
		}
		return tmp;
	}
	
	public void testImport(String filePath ,String userId) throws Exception{
		 Map map = (HashMap)generatePeriod();
		 try{
			 File file = getFile(filePath);
			 List<String[]> tmp = readFile(file);	
			 for(int line=0;line<tmp.size();line++){					
					String[] datas = tmp.get(line);
					if(line==0){	

						 mappingRateHeader(file, datas,userId);	
					}

			}//end for loop(line)
		 }
		 catch(Exception e){
			 e.printStackTrace();
		 }
	}
	
	
	public int importRate(String filePath ,String userId) throws Exception{
		int res = -1;
		Connection conn = null;
		boolean isExistOlderHeader = false;
		boolean isImport  = false;
		ResourceBundle prop = null;
		
		try{
			 prop = PropsUtils.getProps(Constant.PROP_CONFIG_SYSTEM);
			
			 File file = getFile(filePath);
			 String asOfDate = "";
			 String asOfTime = "";
			 Map map = (HashMap)generatePeriod();
			 
			 TRateHeader header = null;
			 List<TRateDetail> tRateDetailList = new ArrayList();
			 TRateHeaderService hService = new TRateHeaderService();
			 TRateDetailService dService = new TRateDetailService();
			 
			 setMessage();

			 if(commonUtils.isNotEmpty(file)){
				List<String[]> tmp = readFile(file);				
				conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
				
				if(tmp!=null){
					try{
						for(int line=0;line<tmp.size();line++){					
							String[] datas = tmp.get(line);
							if(line==0){	
								 asOfDate = datas[0];
								 asOfTime = datas[2];
								 header = mappingRateHeader(file, datas,userId);	
							}
							if(line > 1){
								if(commonUtils.isNotEmpty(header)){
									mappingRateDetails(map, header,tRateDetailList,datas,userId);							
								}							
							}
						}//end for loop(line)
						
						logImport.info("Insert import rate size = " + tmp.size());
					}
					catch(Exception e){
						logImport.error(e);
						log.error(e);
						e.printStackTrace();
						throw new Exception("Save Fail");
					}
					
				}//case data is not null;
				//compare as_of_date is after/equals cut_off_date_time
				String  importDate = commonUtils.formatDate(new Date(), "dd/MM/yyyy");
				Date myDatetime    = commonUtils.convertStringtoSQLDate(commonUtils.getcurrentDatetime(),"dd/MM/yyyy HH:mm:ss"); 
				Date cutoffDate    = commonUtils.convertStringtoSQLDate(importDate+" "+prop.getObject("rate_cut_off_time").toString(),"dd/MM/yyyy HH:mm:ss");

				TRateHeader tmpHeader = null;
						
//				if(isAfterDate(asOfDate,importDate)){ //as of date is after import date (import for next day)
//					if(myDatetime.before(cutoffDate)){
//						throw new Exception(message.get("00014")+prop.getObject("rate_cut_off_time").toString());
//					}
//					else{
//						isImport = true;
//						isExistOlderHeader = hService.isExistHeader(header,conn);						
//					}
//				}
//				else 
				
				
				if(isEqualsDate(asOfDate,importDate)){					
					if(hService.isOlderAsOfDateAndTime(header,conn)){
						throw new Exception(message.get("00013"));
					}
					else{
						isImport = true;
						isExistOlderHeader = hService.isExistHeader(header,conn);			
					}
				}else if(isAfterDate(asOfDate,importDate)){
					throw new Exception(message.get("00024"));
				
				}else{
					throw new Exception(message.get("00013"));
				}
				
				if(isImport){
					if(isExistOlderHeader){
						tmpHeader = hService.getCurrentActiveHeader(header, conn);
						res =  hService.insert(header, conn);	
						try{
							if(res > 0){
								 
								 res = dService.insert(tRateDetailList, conn);								 
								
								 if(res >-1){
										header.setMessage("SUCCESS");
										res = hService.updateByCondition(header,conn);
										
									    if(res >0){
											if(tmpHeader!=null){//current active header
												 
//												 tmpHeader.setActiveStatus(Constant.INACTIVE_STATUS); //set IN ACTIVE
//												 tmpHeader.setUpdateBy(userId);
//												 res = hService.updateByCondition(tmpHeader,conn);
//												 
//												 if(res > 0){
//													 TRateDetail d = new TRateDetail();
//													 d.setRateHeaderId(tmpHeader.getId());
//													 res = dService.delete(d,conn); //delete detail of current active
//													 
//											     }		
											
												res = hService.deleteRateHeader(conn, tmpHeader.getId());
												
												logImport.debug("Delete TRateHeader id = " + tmpHeader.getId() + " is " + res);
												log.debug("Delete TRateHeader id = " + tmpHeader.getId() + " is " + res);
											}									
										}
									    
									}
								 logImport.debug("res>"+res);
								 log.debug("res>"+res);
								   							
							}
							if(res > -1){
					        	 conn.commit();
					        	 res = 1;
					        	 //callProc();
					        	 new ImportRateProcessThread().start();
					        }
					        else{
					        	 conn.rollback();
					        }	
						}catch(Exception er){						   
						    //case insert new detail error
							header.setActiveStatus(Constant.INACTIVE_STATUS);
							header.setMessage(er.getMessage());
							hService.updateByCondition(header,conn);
							dService.delete(tRateDetailList.get(0),conn); 
							conn.commit();
							logImport.error(er);
							log.error(er);
							throw new Exception("Save Fail");
						}
					}//insert & update
					else{
						res =  hService.insert(header, conn);	
						
						if(res > 0){						
							try{
								res = dService.insert(tRateDetailList, conn);
						    
							}catch(Exception er){
							    //case insert new detail error
								header.setActiveStatus(Constant.INACTIVE_STATUS);
								header.setMessage(er.getMessage());
								hService.updateByCondition(header,conn);
								dService.delete(tRateDetailList.get(0),conn); 
								conn.commit();	
								logImport.error(er);
								log.error(er);
								throw new Exception("Save Fail");
							}							
							if(res >-1){
								header.setMessage("SUCCESS");
								res = hService.updateByCondition(header,conn);	
								if(res > -1){
						        	 conn.commit();
						        	 res = 1;
						        	 //callProc();
						        	 new ImportRateProcessThread().start();
						        }
						        else{
						        	 conn.rollback();
						        }
							}					
						
						}
						else{
							throw new Exception("Save Fail");
						}
							
					}//insert new only
				}					
			 }
			 else{
				 throw new FileNotFoundException();
			 }
		}
		catch(Exception e){
			logImport.error(e);
			log.error("e>>"+e);
			throw e;
		}finally {
			if(conn != null ) conn.close();
		}
		return res;
	}
	
	public void setMessage() throws Exception{
		Connection conn 			= null;
		PreparedStatement pstm 		= null;
		ResultSet rs				= null;
		List<CMessage> messageList 	= new ArrayList<CMessage>();
		MessageDao dao 				= new MessageDao();
		
		try{
			conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO); // get connection fxmargin from mssql
			
			messageList = dao.getMessage(conn, pstm, rs);
			
			if(messageList != null && messageList.size() > 0){
				
				for(CMessage mes : messageList) {
					message.put(mes.getCode(), mes.getNameEN());
				}
			}
			
		} catch (Exception e){
			log.error(e);
			e.printStackTrace();
		} finally {
			if(conn != null ) conn.close();
			if(pstm != null ) pstm.close();
			if(rs   != null ) rs.close();
		}
		
	}
	
	
	private boolean isEqualsDate(String date1,String date2){
		boolean isEq = false;
		 try {
			 Date dt1= commonUtils.convertStringtoSQLDate(date1,"dd/MM/yyyy");
			 Date dt2= commonUtils.convertStringtoSQLDate(date2,"dd/MM/yyyy");
			 if(dt1.equals(dt2)){
			    isEq = true;
			 }
		  
		 } catch (Exception e) {
				log.error(e);
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return isEq;
	}
	
	private boolean isAfterDate(String date1,String date2){
		boolean isEq = false;
		 try {
			 Date dt1= commonUtils.convertStringtoSQLDate(date1,"dd/MM/yyyy");
			 Date dt2= commonUtils.convertStringtoSQLDate(date2,"dd/MM/yyyy");
			 if(dt1.after(dt2)){
			    isEq = true;
			 }
		  
		 } catch (Exception e) {
				log.error(e);
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return isEq;
	}
	
	
	public static void main(String[] param){
		ImportRateService s = new ImportRateService();
		
		try {
			if(param.length != 2){
				System.out.println("Please insert 2 parameters. -- 1.filePath 2.userId");
				return;
			}
			
			System.out.println("Processing importRate");
			System.out.println(">filePath: "+param[0]);
			System.out.println(">userId: "+param[1]);
			
			s.importRate(param[0], param[1]);
			
			System.out.println("importRate success!");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class ImportRateProcessThread extends Thread {
	private Logger log = Logger.getLogger(Constant.LOG_FX);
    public ImportRateProcessThread() {
	  super();
    }
    public void run() {
    	log.debug("ImportRateProcessThread.Start Process at "+commonUtils.getcurrentDatetime());
    	TRateHeaderService svc = new TRateHeaderService();
	    try {
	    	svc.callProc();
			
		} catch (Exception e) {
			log.error(e);
			e.printStackTrace();
		}		
	    log.debug("ImportRateProcessThread.End Process at "+commonUtils.getcurrentDatetime());
    }
}